home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-07-15 | 4.3 KB | 168 lines | [TEXT/MPS ] |
- {
-
- TranslateRotate.p
-
- Many people are uncomfortable with Apple's fixed-point data types,
- because they can't be used with normal operator arithmetic and
- because their representation is not easily readable (though it
- is easily converted to integer types). Here's something to show
- how simple it really is.
-
- TranslateRotate does two-dimensional translation and rotations
- in word-size coordinates, using fixed-point math. Each routine
- is passed info for a transform matrix which tells the routine what
- to do with the fPoint argument. Each routine then does its thing
- on its fPoint argument, returning the new fPoint position.
-
- The purpose of TranslateRotate is to provide a simple demo of the
- use of Fixed and Fract math in basic 2D transformations. The
- procedures sacrifice speed for clarity in their use of intermediate
- variables, etc.
-
- Fixed-point math has broad applications for speed-sensitive code,
- and is accurate enough for any screen graphics computations, if
- you are careful to perform your computations so as to minimize
- error propagation (do multiplications first, divisions last, for
- example). There are few reasons to use floating point unless you
- demand error smaller than 2 to the -16.
-
- For demonstration purposes, the two routines (one for rotation,
- one for translation) are called together from an MPW shell
- application. The application prompts you for x,y translation
- values and a rotation value in radians. It then calls a routine
- which first rotates and then translates the point. Type rotation
- = 999 to escape the program.
-
- Points are stored as fWords, which are of size WORD.
-
- Billster
- Apple Computer
- 5/10/91
-
- }
-
- Program TranslateRotate;
-
- uses PasLibIntf,FixMath,ToolUtils;
-
- const
- FracToIntegerConversion = 1073741824; { Divide by this to turn Frac into truncated int }
- FixToIntegerConversion = 65536; { Divide by this to turn Fixed into truncated int }
-
- type
- fWord = integer; { This is the type for linear measurement hereafter }
-
- fPoint = record { This is the type for an arbitrary point }
- x : fWord;
- y : fWord;
- end;
-
- TransRot2D = record { This record holds all the information for the }
- x : fWord; { transformation or rotation of a point }
- y : fWord;
- rot : Fixed;
- end;
-
- TransRot3D = record { This would hold the information for the }
- x : fWord; { translation/rotation in the 3D case. }
- y : fWord; { The routines are not implemented in this }
- z : fWord; { sample, however. }
- rotXY : Fixed;
- rotYZ : Fixed;
- rotXZ : Fixed;
- end;
-
- var
- transformInput : transRot2D;
- fPtInput, fPtResult : fPoint;
-
-
-
-
-
- { Routines for translation and rotation }
-
-
-
- Function Rotate2D(theFPoint: fPoint; theTransRot : transRot2D) : fPoint;
- var
- sinRot, cosRot: Fract;
- begin
- sinRot := FracSin(theTransRot.rot);
- cosRot := FracCos(theTransRot.rot);
-
- Rotate2D.x := fWord( FracMul(cosRot,theFPoint.x) - FracMul(sinRot,theFPoint.y) );
- Rotate2D.y := fWord( FracMul(sinRot,theFPoint.x) + FracMul(cosRot,theFPoint.y) );
-
- { The above is a computation of:
-
- | cos(rot) -sin(rot) | | x |
- | | | |
- | sin(rot) cos(rot) | | y |
- }
- end;
-
-
-
- Function Translate2D(theFPoint: fPoint; theTransRot : transRot2D) : fPoint;
- begin
- Translate2D.x := theFPoint.x + theTransRot.x;
- Translate2D.y := theFPoint.y + theTransRot.y;
-
- { The above is a computation of:
-
- | tranlate2D.x 0 | | x |
- | | | |
- | 0 tranlate2D.y | | y |
- }
- end;
-
-
-
-
-
- { Routines specific to the MPW Shell tool }
-
-
- Procedure Initialize; { Start us off somewhere }
- begin
- fPtInput.x := 100;
- fPtInput.y := 100;
- end;
-
-
-
- Function TransRotate2D(theFPoint: fPoint; theTransRot : transRot2D) : fPoint;
- { Calls Rotate2D, then Translate2D }
- begin
- TransRotate2D := Translate2D(Rotate2D(theFPoint,theTransRot),theTransRot);
- end;
-
-
-
- Function GetNext2DTransRot : transRot2D;
- { This routine just gets data for the trans/rotate record }
- var
- radians : real;
- begin
- writeln('X: ');
- readln(GetNext2DTransRot.x);
- writeln('Y: ');
- readln(GetNext2DTransRot.y);
- writeln('Rotation: ');
- readln(radians);
- GetNext2DTransRot.rot := round(radians * FixToIntegerConversion);
- end;
-
-
-
- begin
- Initialize;
-
- transformInput := GetNext2DTransRot;
- while transformInput.rot <> (999 * FixToIntegerConversion) do begin
- fPtResult := TransRotate2D(fPtInput, transformInput);
- writeln('Output: ',fPtResult.x,fPtResult.y);
- transformInput := GetNext2DTransRot;
- end;
- end.